/*
 * @Author: aim-leo
 * @Date: 2019-03-07 11:57:15
 * @Last Modified by: aim-leo
 * @Last Modified time: 2019-07-29 13:56:40
 */

const FastestValidator = require('fastest-validator')
const validator = new FastestValidator()

const Util = require('../util')

class TargetControler extends Util {
  constructor(service) {
    super()
    this.service = service
  }

  async insert(params) {
    const [err, res] = await this.service.insert(params)

    return err || res
  }

  async query(params, populate) {
    try {
      if (params.filters && this.isType(params.filters, '')) {
        if (!this.isJson(params.filters)) {
          return this.rejectRes(-1, 'filters expected a json string!')
        }
        params.filters = JSON.parse(params.filters)
      }
      if (params.sort && this.isType(params.sort, '')) {
        if (!this.isJson(params.sort)) {
          return this.rejectRes(-1, 'sort expected a json string!')
        }
        params.sort = JSON.parse(params.sort)
      }
      if (params.search && this.isType(params.search, '')) {
        if (!this.isJson(params.search)) {
          return this.rejectRes(
            -1,
            'search expected a json string like: { value: value, scope: [scope1, scope2] }!'
          )
        }
        const search = JSON.parse(params.search)
        if (
          !('value' in search) ||
          !('scope' in search) ||
          search.scope.length < 1
        ) {
          return this.rejectRes(
            -1,
            'search expected a json string like: { value: value, scope: [scope1, scope2] }!'
          )
        }

        const searchFilters = []

        const reg = {
          $regex: new RegExp(decodeURIComponent(search.value), 'i')
        }

        for (const scope of search.scope) {
          searchFilters.push({
            [scope]: reg
          })
        }

        params.filters = {
          ...params.filters,
          $or: searchFilters
        }
      }

      const schema = {
        page: {
          type: 'number',
          min: 0,
          optional: true,
          convert: true
        },
        limit: {
          type: 'number',
          min: 10,
          max: 100,
          optional: true,
          convert: true
        },
        all: {
          type: 'number',
          min: 0,
          max: 1,
          optional: true,
          convert: true
        },
        id: {
          type: 'string',
          length: 24,
          optional: true
        },
        filters: {
          type: 'object',
          optional: true
        },
        query: {
          type: 'object',
          optional: true
        },
        sort: {
          type: 'object',
          optional: true
        },
        select: {
          type: 'object',
          optional: true
        }
      }
      const validError = validator.validate(params, schema)
      if (validError && validError.length > 0) {
        return this.rejectRes(-1, validError[0].message)
      }
      // default
      params.page = parseInt(params.page) || 1
      params.limit = parseInt(params.limit) || 10
      // query
      if (params.id) {
        const queryOne = await this.service.queryById(params.id, {
          populate,
          select: params.select
        })
        if (!queryOne) return this.rejectRes(1, '查询出错, 未找到该项')
        queryOne.pwd = undefined
        return this.resolveRes(1, '查询成功', { list: queryOne, count: 1 })
      }
      const count = await this.service.count({
        filters: params.filters
      })
      const list = (
        await this.service.query({
          params,
          populate,
          filters: params.filters,
          query: params.query,
          sort: params.sort,
          select: params.select
        })
      ).map(item => {
        item.pwd = undefined

        return item
      })
      return this.resolveRes(1, '查询成功', {
        list,
        count,
        pageIn: params.page
      })
    } catch (e) {
      return this.rejectRes(1, '查询出错', e)
    }
  }

  async delete(params) {
    try {
      const schema = {
        id: {
          type: 'string',
          length: 24
        }
      }
      const validError = validator.validate(params, schema)
      if (validError && validError.length > 0) {
        return this.rejectRes(-1, validError[0].message)
      }
      const res = await this.service.deleteById(params)
      if (!res || res.deletedCount === 0) {
        return this.rejectRes(-1, '删除失败,不存在该条目')
      }
      return this.resolveRes(1, '删除成功', res)
    } catch (e) {
      return this.rejectRes(-1, '删除失败', e)
    }
  }

  async update(params, schema) {
    try {
      schema = schema || {
        id: {
          type: 'string',
          length: 24
        }
      }
      const validError = validator.validate(params, schema)
      if (validError && validError.length > 0) {
        return this.rejectRes(-1, validError[0].message)
      }
      const exsist = await this.service.checkById(params.id)
      if (!exsist) {
        return this.rejectRes(-1, '不存在该条目，修改失败')
      }
      const id = params.id
      delete params.id
      const [err, res] = await this.service.update(params, { _id: id })
      return err || res
    } catch (e) {
      return this.rejectRes(-1, '修改失败', e)
    }
  }
}

module.exports = TargetControler
